#region File Description
//-----------------------------------------------------------------------------
// Author: JCBDigger
// URL: http://Games.DiscoverThat.co.uk
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Graphics.PackedVector;
using System;
using System.Threading;
using AssetData;
using AssetContent;
#endregion

namespace Engine
{
    /// <summary>
    /// Helper to manage the configuable particle effect.
    /// </summary>
    public class ParticleHolder
    {
        /// <summary>
        /// A name to identify the settings in the list.
        /// </summary>
        private string uniqueName = "";
        /// <summary>
        /// A name to identify the settings in the list.
        /// </summary>
        public string UniqueName
        {
            get { return uniqueName; }
            set { uniqueName = value; }
        }
        private bool enabled = true;
        public bool Enabled
        {
            get { return enabled; }
            set { enabled = value; }
        }
        /// <summary>
        /// True if the particle is enabled and the emitter is active
        /// </summary>
        public bool Active
        {
            get { return enabled && emitter != null && emitter.Active; }
        }


        /// <summary>
        /// The particle effect.
        /// </summary>
        private ParticleSystem particle;
        /// <summary>
        /// Where the particles appear from.
        /// </summary>
        private ParticleEmitter emitter;
        /// <summary>
        /// The current image used by the particle effect.
        /// </summary>
        private Texture2D texture;

        private Random random = new Random();

        public ParticleHolder()
        {
        }

        public ParticleHolder(string withName)
        {
            uniqueName = withName;
        }

        /// <summary>
        /// Load the effect from the content manager and create the particle system.
        /// Uses a built in smoke effect.
        /// Returns the name used.
        /// </summary>
        public string LoadInitialContent(ModelViewerControl modelViewerControl)
        {
            SetEmitter(modelViewerControl.GetNewEmitter());
            Loader contentLoad = new Loader(modelViewerControl.Services);
            Effect particleEffect = contentLoad.GetEffect("ParticleEffect");
            particle = new ParticleSystem(modelViewerControl.GraphicsDevice, particleEffect);
            ParticleSettings settings = contentLoad.GetParticleSettings(GlobalSettings.particleBuiltInName);
            uniqueName = GlobalSettings.particleBuiltInName;
            SetParticleSettings(settings, true);
            Texture2D image = contentLoad.GetImage(settings.GetAssetNameWithContentPath());
            ParticleImage pImage = new ParticleImage(settings.GetImageFileName(), image);
            SetParticleTexture(pImage);
            modelViewerControl.AddOrUpdateImage(pImage);
            return UniqueName;
        }
        /// <summary>
        /// Add a new particle effect.
        /// </summary>
        public void AddNewParticles(ModelViewerControl modelViewerControl, ParticleSettings settings, ParticleEmitter emit, ParticleImage pImage)
        {
            SetEmitter(emit);
            Loader contentLoad = new Loader(modelViewerControl.Services);
            Effect particleEffect = contentLoad.GetEffect("ParticleEffect");
            particle = new ParticleSystem(modelViewerControl.GraphicsDevice, particleEffect);
            SetParticleSettings(settings, true);
            SetParticleTexture(pImage);
        }

        /// <summary>
        /// Change the effect settings.
        /// Changing the buffer size will reset the particle.
        /// </summary>
        public void SetParticleSettings(ParticleSettings settings, bool changeBufferSize)
        {
            if (changeBufferSize && emitter != null)
            {
                emitter.Deactivate();
            }
            particle.ChangeParticleSettings(settings, changeBufferSize);
            if (changeBufferSize)
            {
                Reactivate();
            }
        }

        /// <summary>
        /// Change the image used by the effect.
        /// </summary>
        public void SetParticleTexture(Texture2D image, string fileName)
        {
            if (image != null)
            {
                texture = image;
                particle.ChangeParticleTexture(image);
                particle.ChangeTextureName(fileName);
                Reactivate();
            }
        }
        /// <summary>
        /// Change the image used by the effect.
        /// </summary>
        public void SetParticleTexture(ParticleImage pImage)
        {
            if (pImage != null)
            {
                SetParticleTexture(pImage.Image, pImage.Name);
            }
        }
        /// <summary>
        /// Must add an emitter before drawing.
        /// This will clone the emitter and activate it.
        /// This will add or change an emitter.
        /// Ignored if the emitter is null.
        /// </summary>
        public void SetEmitter(ParticleEmitter emit)
        {
            if (emit != null)
            {
                if (emitter != null)
                {
                    emitter.Deactivate();
                }
                emitter = emit.Clone();
                Reactivate();
            }
        }

        public Texture2D GetCurrentTexture()
        {
            return texture;
        }

        public string GetTextureName()
        {
            return particle.Settings.TextureName;
        }

        public string GetEmitterName()
        {
            if (emitter == null)
            {
                return "None";
            }
            return emitter.ID;
        }

        public ParticleSettings GetParticleSettings()
        {
            return particle.Settings;
        }

        public void Update(GameTimeMirror gameTime)
        {
            if (!Enabled)
            {
                return;
            }
            if (emitter != null)
            {
                emitter.Update(gameTime, random);
            }
            if (particle != null)
            {
                particle.Update(gameTime);
            }
        }

        public void Draw(GameTimeMirror gameTime, ref Matrix view, ref Matrix projection)
        {
            if (Enabled && particle != null)
            {
                particle.Draw(gameTime, ref view, ref projection);
            }
        }

        /////////////////////////////////////////////////////////////////////
        //
        #region Helpers

        /// <summary>
        /// Force to activate even if the emitter is already active.
        /// </summary>
        public void Reactivate()
        {
            if (emitter == null)
            {
                return;
            }
            emitter.Deactivate();
            Thread.Sleep(2);
            Activate();
        }

        /// <summary>
        /// Only activate if the emitter is not already acive.
        /// </summary>
        private void Activate()
        {
            if (emitter != null && !emitter.Active && particle != null)
            {
                emitter.Activate(particle);
            }
        }

        #endregion
        //
        /////////////////////////////////////////////////////////////////////

    }
}
